package com.qiyu.tech.task.futurev2;

import java.util.concurrent.Future;

/**
 * @Author idea
 * @Date created in 8:42 下午 2020/11/30
 */
public class FutureTask<T> implements RunnableFuture<T>{

    private T realObject;

    private Callable<T> callable;

    private volatile short status;

    private static final short NEW          = 0;
    private static final short COMPLETING   = 1;
    private static final short NORMAL       = 2;
    private static final short EXCEPTIONAL  = 3;
    private static final short CANCELLED    = 4;
    private static final short INTERRUPTING = 5;
    private static final short INTERRUPTED  = 6;


    public FutureTask(Callable callable){
        this.callable = callable;
        this.status = NEW;
    }

    @Override
    public T get() throws InterruptedException {
        if(status < NORMAL) {
            this.awaitDone();
        }
        if(status == NORMAL){
            return realObject;
        }
        return null;
    }

    private void awaitDone() throws InterruptedException {
        while (true){
            if(Thread.currentThread().isInterrupted()){
                status = INTERRUPTED;
                throw new InterruptedException();
            }
            if(status == NORMAL) {
                break;
            }
            if(status == CANCELLED) {
                break;
            }
        }
    }

    @Override
    public void run() {
        this.realObject = callable.call();
        this.status = NORMAL;
    }

    @Override
    public boolean isCancel() {
        return status == CANCELLED  || status == INTERRUPTED;
    }



    @Override
    public Object get(long timeOut) throws InterruptedException {
        return this.get();
    }

    @Override
    public boolean cancel() {
        status=CANCELLED;
        return true;
    }

    @Override
    public boolean isDone() {
        return status == NORMAL;
    }
}
